Skip to content

fix: configure sequences after import #946

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 3, 2025

Conversation

gfyrag
Copy link
Contributor

@gfyrag gfyrag commented May 22, 2025

No description provided.

@gfyrag gfyrag requested a review from a team as a code owner May 22, 2025 10:47
Copy link

coderabbitai bot commented May 22, 2025

Warning

Rate limit exceeded

@gfyrag has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 11 minutes and 38 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 703c034 and 4dfcf7f.

📒 Files selected for processing (3)
  • internal/controller/system/state_tracker.go (2 hunks)
  • test/e2e/api_ledgers_import_test.go (2 hunks)
  • test/e2e/app_lifecycle_test.go (1 hunks)

"""

Walkthrough

Concurrency control was added to the ledger state management by introducing a read-write mutex in the controller. The ledger state update and sequence resets now occur conditionally and within a transactional block, with improved error handling. End-to-end tests were updated to verify sequence restoration and clarify concurrency test logic and expectations.

Changes

File(s) Change Summary
internal/controller/system/state_tracker.go Added a RWMutex to controllerFacade for concurrency safety, updated handleState to use locking for ledger state, perform conditional updates and sequence resets within a transaction, and improved error handling.
test/e2e/api_ledgers_import_test.go Enhanced import tests with a check for transaction sequence restoration and clarified concurrency test comments and query filtering for PostgreSQL locks.
test/e2e/app_lifecycle_test.go Updated advisory lock count assertion to expect only the number of transactions, removing the extra lock for logs sync hashing from the expectation.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ControllerFacade
    participant LedgerDB

    Client->>ControllerFacade: handleState(ctx, dryRun, fn)
    ControllerFacade->>ControllerFacade: Acquire read lock on ledger state
    alt Ledger state is StateInitializing
        ControllerFacade->>LedgerDB: Begin transaction
        ControllerFacade->>LedgerDB: Conditionally update ledger state in DB
        alt Update affected rows
            ControllerFacade->>LedgerDB: Reset transaction and log sequences
        end
        ControllerFacade->>ControllerFacade: Execute callback function
        ControllerFacade->>LedgerDB: Commit transaction
        ControllerFacade->>ControllerFacade: Acquire write lock, update in-memory state
    else
        ControllerFacade->>ControllerFacade: Proceed without transactional locking
        ControllerFacade->>ControllerFacade: Execute callback function
    end
    ControllerFacade-->>Client: Return result or error
Loading

Possibly related PRs

Suggested reviewers

  • fguery

Poem

A mutex now guards the ledger’s state,
Ensuring no race will seal its fate.
Sequences reset, with care they’re tracked,
Tests now check IDs—no detail lacked.
With locks and checks, our code’s robust—
In rabbits’ work, you can always trust! 🐇
"""

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

codecov bot commented May 22, 2025

Codecov Report

Attention: Patch coverage is 70.96774% with 18 lines in your changes missing coverage. Please review.

Project coverage is 82.25%. Comparing base (6b3e2e7) to head (4dfcf7f).
Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
internal/controller/system/state_tracker.go 70.96% 12 Missing and 6 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #946      +/-   ##
==========================================
- Coverage   82.25%   82.25%   -0.01%     
==========================================
  Files         141      141              
  Lines        7788     7883      +95     
==========================================
+ Hits         6406     6484      +78     
- Misses       1057     1068      +11     
- Partials      325      331       +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
internal/controller/system/state_tracker.go (1)

40-83: Consider handling NULL result from MAX operation

When selecting the maximum ID from a table, consider handling the case where the table might be empty (resulting in NULL).

-            select setval(
-                '"%s"."transaction_id_%d"', 
-                (
-                    select max(id) from "%s".transactions where ledger = '%s'
-                )::bigint
-            )
+            select setval(
+                '"%s"."transaction_id_%d"', 
+                COALESCE((
+                    select max(id) from "%s".transactions where ledger = '%s'
+                ), 0)::bigint
+            )
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b3e2e7 and 31aaae9.

📒 Files selected for processing (3)
  • internal/controller/system/state_tracker.go (2 hunks)
  • test/e2e/api_ledgers_import_test.go (2 hunks)
  • test/e2e/app_lifecycle_test.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Dirty
  • GitHub Check: Tests
🔇 Additional comments (9)
test/e2e/app_lifecycle_test.go (1)

139-140: Expectation corrected to match the actual concurrency model

The updated test now correctly expects exactly countTransactions advisory locks instead of countTransactions + 1. This aligns with the concurrency control improvements made in the state tracker where the ledger state update and sequence resets happen in a more efficient transaction.

test/e2e/api_ledgers_import_test.go (2)

352-366: Good addition: Testing sequence restoration after import

This new test verifies that transaction IDs continue in the correct sequence after an import operation. It confirms that the transaction sequence is properly reset by ensuring the next transaction ID is exactly one greater than the first transaction ID from the original ledger.


444-451: Clarified test comments and SQL filter

The updated comment now correctly explains that locking the logs table blocks the attempt to set the transaction sequence value, rather than just blocking log insertion. The SQL filter was appropriately updated to match queries containing "select setval" instead of INSERT statements, which accurately reflects what's being tested.

internal/controller/system/state_tracker.go (6)

12-12: Added sync package for concurrent access control

Good addition of the sync package to support the mutex-based concurrency control.


17-17: Added mutex for concurrency safety

Added a read-write mutex to protect access to the ledger state, ensuring thread-safe operations in a concurrent environment.


22-26: Improved thread safety with proper locking

The read lock ensures safe concurrent access to the ledger state. Using a local variable to store the state prevents race conditions between reading and decision-making.


40-83: Added sequence reset logic within a transactional context

This change conditionally updates ledger state and resets both transaction and log ID sequences based on maximum existing IDs. The approach ensures that:

  1. Updates only happen when the ledger is in initializing state
  2. Sequence values are set correctly based on existing data
  3. All operations occur in a single transaction for atomicity

Good error handling with descriptive error messages is provided for each operation.


85-89: Improved function invocation within transaction

The function invocation is now properly wrapped within the transaction, ensuring that any operations performed by the function are part of the same atomic unit of work.


94-96: Enhanced error handling for transaction commit

The error message now includes more context about the failure, which will help with debugging issues.

@gfyrag gfyrag force-pushed the fix/configure-sequences-after-import branch from 31aaae9 to 2b1be50 Compare May 22, 2025 14:32
@gfyrag gfyrag force-pushed the fix/configure-sequences-after-import branch 2 times, most recently from 3557e93 to 703c034 Compare June 3, 2025 09:06
@gfyrag gfyrag enabled auto-merge June 3, 2025 09:09
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/e2e/api_ledgers_import_test.go (1)

313-313: Remove focused test marker before merging.

The FIt focuses this test to run exclusively, which is typically used for debugging and should not be committed to production code.

Apply this diff to restore normal test execution:

-						FIt("should be ok", func(specContext SpecContext) {
+						It("should be ok", func(specContext SpecContext) {
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3557e93 and 703c034.

📒 Files selected for processing (3)
  • internal/controller/system/state_tracker.go (2 hunks)
  • test/e2e/api_ledgers_import_test.go (3 hunks)
  • test/e2e/app_lifecycle_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/e2e/app_lifecycle_test.go
  • internal/controller/system/state_tracker.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
test/e2e/api_ledgers_import_test.go (6)
pkg/client/ledger.go (1)
  • Ledger (19-24)
pkg/client/v2.go (1)
  • V2 (19-21)
pkg/client/models/operations/v2createtransaction.go (1)
  • V2CreateTransactionRequest (9-25)
pkg/client/models/components/v2posttransaction.go (1)
  • V2PostTransaction (58-68)
pkg/client/models/components/v2posting.go (1)
  • V2Posting (10-15)
pkg/client/models/components/v2transactionscursorresponse.go (1)
  • V2TransactionsCursorResponse (48-50)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Dirty
  • GitHub Check: Tests
🔇 Additional comments (1)
test/e2e/api_ledgers_import_test.go (1)

461-462: LGTM! Comment and query updates accurately reflect the blocking behavior.

The updated comments and SQL query correctly clarify that the test verifies blocking on sequence setting (select setval) rather than log insertion, which aligns with the concurrency control improvements mentioned in the PR objectives.

Also applies to: 467-467

Comment on lines +352 to +383
By("Checking sequence restoration by creating a new transaction with dry run", func() {
tx, err := Wait(specContext, DeferClient(testServer)).Ledger.V2.CreateTransaction(ctx, operations.V2CreateTransactionRequest{
Ledger: createLedgerRequest.Ledger,
DryRun: pointer.For(true),
V2PostTransaction: components.V2PostTransaction{
Postings: []components.V2Posting{{
Source: "world",
Destination: "dst",
Asset: "USD",
Amount: big.NewInt(100),
}},
},
})
Expect(err).To(BeNil())
Expect(tx.V2CreateTransactionResponse.Data.ID.Uint64()).To(Equal(transactionsFromOriginalLedger.V2TransactionsCursorResponse.Cursor.Data[0].ID.Uint64() + 1))
})

By("Checking sequence restoration by creating a new transaction", func() {
tx, err := Wait(specContext, DeferClient(testServer)).Ledger.V2.CreateTransaction(ctx, operations.V2CreateTransactionRequest{
Ledger: createLedgerRequest.Ledger,
V2PostTransaction: components.V2PostTransaction{
Postings: []components.V2Posting{{
Source: "world",
Destination: "dst",
Asset: "USD",
Amount: big.NewInt(100),
}},
},
})
Expect(err).To(BeNil())
Expect(tx.V2CreateTransactionResponse.Data.ID.Uint64()).To(Equal(transactionsFromOriginalLedger.V2TransactionsCursorResponse.Cursor.Data[0].ID.Uint64() + 2))
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix test logic for sequence restoration verification.

The sequence restoration tests are creating transactions on the original ledger (createLedgerRequest.Ledger) instead of the imported ledger (ledgerCopyName). This doesn't verify that the import process correctly restored sequences in the copied ledger.

Additionally, the test assumes transactionsFromOriginalLedger.V2TransactionsCursorResponse.Cursor.Data[0] is the first transaction by ID, but this depends on the ordering of the response data.

Apply this diff to test sequence restoration on the correct ledger and use a more reliable approach:

 							By("Checking sequence restoration by creating a new transaction with dry run", func() {
+								// Get the highest transaction ID from the imported ledger
+								maxTxID := uint64(0)
+								for _, tx := range transactionsFromNewLedger.V2TransactionsCursorResponse.Cursor.Data {
+									if tx.ID.Uint64() > maxTxID {
+										maxTxID = tx.ID.Uint64()
+									}
+								}
+
 								tx, err := Wait(specContext, DeferClient(testServer)).Ledger.V2.CreateTransaction(ctx, operations.V2CreateTransactionRequest{
-									Ledger: createLedgerRequest.Ledger,
+									Ledger: ledgerCopyName,
 									DryRun: pointer.For(true),
 									V2PostTransaction: components.V2PostTransaction{
 										Postings: []components.V2Posting{{
 											Source:      "world",
 											Destination: "dst",
 											Asset:       "USD",
 											Amount:      big.NewInt(100),
 										}},
 									},
 								})
 								Expect(err).To(BeNil())
-								Expect(tx.V2CreateTransactionResponse.Data.ID.Uint64()).To(Equal(transactionsFromOriginalLedger.V2TransactionsCursorResponse.Cursor.Data[0].ID.Uint64() + 1))
+								Expect(tx.V2CreateTransactionResponse.Data.ID.Uint64()).To(Equal(maxTxID + 1))
 							})

 							By("Checking sequence restoration by creating a new transaction", func() {
 								tx, err := Wait(specContext, DeferClient(testServer)).Ledger.V2.CreateTransaction(ctx, operations.V2CreateTransactionRequest{
-									Ledger: createLedgerRequest.Ledger,
+									Ledger: ledgerCopyName,
 									V2PostTransaction: components.V2PostTransaction{
 										Postings: []components.V2Posting{{
 											Source:      "world",
 											Destination: "dst",
 											Asset:       "USD",
 											Amount:      big.NewInt(100),
 										}},
 									},
 								})
 								Expect(err).To(BeNil())
-								Expect(tx.V2CreateTransactionResponse.Data.ID.Uint64()).To(Equal(transactionsFromOriginalLedger.V2TransactionsCursorResponse.Cursor.Data[0].ID.Uint64() + 2))
+								Expect(tx.V2CreateTransactionResponse.Data.ID.Uint64()).To(Equal(maxTxID + 2))
 							})

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In test/e2e/api_ledgers_import_test.go around lines 352 to 383, the test is
incorrectly creating transactions on the original ledger instead of the imported
ledger, which fails to verify sequence restoration on the copied ledger. Update
the ledger field in the CreateTransaction requests to use the imported ledger
identifier (ledgerCopyName). Also, replace the reliance on the first element of
transactionsFromOriginalLedger.V2TransactionsCursorResponse.Cursor.Data for ID
comparison with a more reliable method, such as explicitly determining the
highest existing transaction ID before the test and comparing against that to
ensure correct sequence increment.

@gfyrag gfyrag force-pushed the fix/configure-sequences-after-import branch from 703c034 to 4dfcf7f Compare June 3, 2025 09:22
@gfyrag gfyrag added this pull request to the merge queue Jun 3, 2025
Merged via the queue into main with commit b9b8f14 Jun 3, 2025
9 of 10 checks passed
@gfyrag gfyrag deleted the fix/configure-sequences-after-import branch June 3, 2025 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants